package ar.uba.fi.celdas.ponderador;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import ar.fi.uba.celdas.interfaces.ambiente.IAccion;
import ar.fi.uba.celdas.interfaces.bc.IBaseConocimientos;
import ar.fi.uba.celdas.interfaces.bc.Regla;
import ar.fi.uba.celdas.interfaces.ponderador.IPonderador;

public class Ponderador implements IPonderador {

	GrafoSituaciones grafo;
	
	@Override
	public void ponderar(List<Regla> plan, IBaseConocimientos base) {
	
	
	 grafo = generarSituaciones(base.getReglas()); //con estas reglas armamos las situaciones
	//Matrices: voy a tener una matriz por cada regla del plan
	 
	 ArrayList<Matriz> matrices=new ArrayList<Matriz>();
	 
	//debug
	 Iterator<String> it=grafo.getNombreSituaciones().iterator();
	 System.out.println();
	 while(it.hasNext())
	 {
		 System.out.print(it.next());
		 System.out.print(" ");
	 }
	 System.out.println();
	 
	//Quiero las acciones del plan y hago las matrices para cada accion... lo que en el libro dice "accion" aca seria una lista de accioens.. 
	 //es lo que lleva de una situacion a otra
	 //Regla1-Matriz1 
	 //Regla2-Matriz2
	 //etc
	 List<Regla> totalReglasAcciones;
	 ArrayList<Situacion> situacionesConocidas =grafo.getSituaciones();
	 Matriz unaMatriz;
	for(Regla unaReglaDelPlan:plan){
		totalReglasAcciones=this.obtenerTodasReglasDeLaBaseConIgualesAcciones(unaReglaDelPlan.getAcciones(), base);//tengo las reglas con igual acciones de la base
		
		unaMatriz=new Matriz(grafo.getCantidadSituaciones());
		
		for(Regla unReglaDelTotal:totalReglasAcciones){
			int fila=darIndiceSale(unReglaDelTotal, situacionesConocidas);
			int columna=darIndiceLlega(unReglaDelTotal, situacionesConocidas);
			unaMatriz.setPos(fila, columna, Integer.valueOf(unReglaDelTotal.getExitos()).floatValue()/Integer.valueOf(unReglaDelTotal.getUso()).floatValue());
		}
		
		matrices.add(unaMatriz);
		
		unaMatriz.imprimirMatriz();
		System.out.println();
	}
	
	//una vez creadas todas las matrices, las multiplico
	Matriz matrizMPresultado=matrices.get(0);
	for(int i=1;i<matrices.size();i++){
		matrizMPresultado=matrizMPresultado.multiplicar(matrices.get(i));
	}

	//en este punto ya tengo la matriz con las probabilidades... TODO:ver como usar estas probabilidades para modificar las utilidades
	matrizMPresultado.imprimirMatriz();
	
	}

	private int darIndiceLlega(Regla unReglaDelTotal,
			ArrayList<Situacion> situacionesConocidas) {
		for(int i=0;i<situacionesConocidas.size();i++){
			if(unReglaDelTotal.getPredicciones().containsAll(situacionesConocidas.get(i).estado)) return i;
		}
		return -1;
	}

	private int darIndiceSale(Regla unReglaDelTotal,
			ArrayList<Situacion> situacionesConocidas) {
		for(int i=0;i<situacionesConocidas.size();i++){
			if(unReglaDelTotal.getCondiciones().containsAll(situacionesConocidas.get(i).estado)) return i;
		}
		return -1;
	}



	private List<Regla> obtenerTodasReglasDeLaBaseConIgualesAcciones(
			List<IAccion> acciones, IBaseConocimientos base) {
		
		List<Regla> resultado = new ArrayList<Regla>();
		
		for(Regla unaRegla:base.getReglas()){
			if(sonIgualesAcciones(unaRegla.getAcciones(),acciones)){//la regla examinada tiene igual set de acciones, la agrego
				resultado.add(unaRegla);
			}
		}
		return resultado;
	}

	public static boolean sonIgualesAcciones(List<IAccion> acciones,
			List<IAccion> acciones2) {
		
		for(int i =0;i<acciones.size();i++){
			if(!acciones.get(i).getNombre().equals(acciones2.get(i).getNombre())){
				return false;
			}
		}
		return true;
	}

	private GrafoSituaciones generarSituaciones(List<Regla> reglas) {
		grafo=new GrafoSituaciones();
		//primero agrego todas las situaciones
		for(Regla regla:reglas){
			Situacion sit=new Situacion(regla.getCondiciones());
			if(!grafo.situacionExiste(sit)){
				grafo.agregarSituacion(sit);
			}
			sit=new Situacion(regla.getPredicciones());
			if(!grafo.situacionExiste(sit)){
				grafo.agregarSituacion(sit);
			}
		}
		
		
		return grafo;
	}

}
